package mi.common.validator;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;

import javax.validation.Valid;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @ProjectName: [ maven 自动化集成测试系统 ]
 * @Author: [ huanghuanlai ]
 * @CreateTime: [ 2015年5月25日 下午7:16:20 ]
 * @Copy: [ dounine.com ]
 * @Version: [ V1.0 ]
 * @Description: [ 自定义统一验证 ]
 */
public class CustomerValidatorAOP {
	
	@Autowired
	private Validator validator;

	@SuppressWarnings("unused")
	private void controllerInvocation() {
		
	}

	public Object doAround(ProceedingJoinPoint joinPoint)
			throws Throwable {
		
		MethodSignature methodSignature = (MethodSignature) joinPoint
				.getSignature();
		Method method = methodSignature.getMethod();
		Annotation[] annotationList = method.getAnnotations();
		Annotation[][] argAnnotations = method.getParameterAnnotations();
		String[] argNames = methodSignature.getParameterNames();
		Object[] args = joinPoint.getArgs();

		methodSignature = null;//gc
		method = null;//gc
		
		for (int i = 0; i < args.length; i++) {
			if (hasValidAnnotations(argAnnotations[i])&&hasRequestBodyAnnotations(annotationList)) {
				Object ret = validateArg(args[i], argNames[i]);
				if (ret != null) {
					return ret;
				}
			}
		}
		
		annotationList = null;//gc
		argAnnotations = null;//gc

		return joinPoint.proceed(args);
	}

	private boolean hasValidAnnotations(Annotation[] annotations) {
		boolean hasValid = false;
		for (Annotation annotation : annotations) {
			if (Valid.class.isInstance(annotation))
				hasValid = true;
		}
		return hasValid;
	}
	
	private boolean hasRequestBodyAnnotations(Annotation[] annotations) {
		boolean hasResponseBody = false;
		for (Annotation annotation : annotations) {
			if (ResponseBody.class.isInstance(annotation))
				hasResponseBody = true;
		}
		return hasResponseBody;
	}

	private JsonResult validateArg(Object arg, String argName) {
		BindingResult result = getBindingResult(arg, argName);
		validator.validate(arg, result);
		if (result.hasErrors()) {
			JsonResult jsonresult = new JsonResult();
			jsonresult.setSuccess(false);
			List<ObjectError> objectErrors = result.getAllErrors();
			for(ObjectError objectError : objectErrors){
				jsonresult.getMsgs().add(objectError.getDefaultMessage());
			}
			jsonresult.setMsg("failure");
			
			result = null;//gc
			
			return jsonresult;
		}
		
		result = null;//gc
		
		return null;
	}

	private BindingResult getBindingResult(Object target, String targetName) {
		return new BeanPropertyBindingResult(target, targetName);
	}
}
